package com.yeyaomai.dksns.flowis.quartz;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import com.yeyaomai.dksns.flowis.dao.DetailDao;
import com.yeyaomai.dksns.flowis.dao.MongoDBBasicDao;
import com.yeyaomai.dksns.flowis.dao.ReferDomainDao;
import com.yeyaomai.dksns.flowis.domain.ReferDomain;
import com.yeyaomai.dksns.flowis.domain.flowisdetail.FlowisStatDetailDTO;
import com.yeyaomai.dksns.flowis.util.CollectionNames;
import com.yeyaomai.dksns.flowis.util.Globals;

/**
 * 来路域名维度统计定时任务类
 * @author xiaqin
 *@date 2012-07-09
 */
public class ReferDomainExecutor extends MongoDBBasicDao<ReferDomain> {

	@Resource
	private DetailDao detailDao;
	
	@Resource
	private ReferDomainDao referDomainDao;
	
	final Logger logger = Logger.getLogger("quartz");
	
	/**
	 * 执行添加操作
	 * 新访客浏览次数,是指从某个域名过来的第一次访问的用户访问端口的网站的页面次数
	 * 站内总浏览数是指从某一域名过来的访问用户访问端口网站的页面次数
	 * @throws ParseException
	 */
	public void saveReferDomain() throws ParseException {
		Date date = new Date();
		Date dates = new Date(date.getTime() - 1 * 3600 * 1000);
		String formDate = Globals.FORMAT_TYPE_A.format(dates);
		String toDate = Globals.FORMAT_TYPE_A.format(date);
		if(formDate.equals(toDate))
		{
			toDate = Globals.FORMAT_TYPE_A.format(new Date(Globals.FORMAT_TYPE_A.parse(toDate).getTime()+1 * 24 * 3600 * 1000));
		}
		referDomainDao.delReferDomainByDateAndDomain(formDate);
		GroupByResults<FlowisStatDetailDTO> result = this.getVisitCountByTime(
				formDate, toDate);
		Integer number = 1;
		for (FlowisStatDetailDTO engine : result) {
			if(engine.getDomain().indexOf("duankou") == -1)
			{
			ReferDomain referDomain = new ReferDomain();
			referDomain.setReferDate(Globals.FORMAT_TYPE_A
					.parse(Globals.FORMAT_TYPE_A.format(dates)));
			referDomain.setDomainName(engine.getDomain());
			referDomain.setVisitCount(engine.getVisitCount());
			Integer uniqueCount = this.getUVByTime(formDate, toDate,
					engine.getDomain());
			referDomain.setUniqueHost(uniqueCount);
			Integer ip = this.getIpByTime(formDate, toDate, engine.getDomain());
			referDomain.setIp(ip);
			Integer newuniqueHost = this.getNewUVByTime(formDate, toDate,
					engine.getDomain());
			referDomain.setNewUniqueHost(newuniqueHost);
			Integer newuniqueCount = this.countReferDomainByTimeAndDomain(formDate, toDate, engine.getDomain(),1);
			referDomain.setNewUniqueHostCount(newuniqueCount);
			Integer standCount = this.countReferDomainByTimeAndDomain(formDate, toDate, engine.getDomain(),2);
			referDomain.setStandCount(standCount);
			referDomainDao.addReferDomain(referDomain);
			number++;
			}
		}
		logger.info(date+"running saveReferDomain Task add Data times of the "+number);
		logger.info("#############################来路域名定时任务执行添加完毕######################");
	}

	/**
	 * 按域名统计访问次数
	 */
	private GroupByResults<FlowisStatDetailDTO> getVisitCountByTime(
			String fromTrendDay, String toTrendDay) {

		String mapFunction = "{ visitCount: 0}";
		String reduceFunction = "function(doc, prev) {prev.visitCount+=1}";
		Criteria criteria = Criteria.where("access_date").gte(fromTrendDay).lt(toTrendDay).and("domain").ne("");
		GroupByResults<FlowisStatDetailDTO> result = detailDao
				.group(criteria, CollectionNames.DOMAIN, mapFunction, reduceFunction, FlowisStatDetailDTO.class);
		return result;
	}

	/**
	 * 定时任务处理UV
	 */
	private int getUVByTime(String formDate, String toDate, String domain) {
		String mapFunction = "{ visitCount: 0}";
		String reduceFunction = "function(doc, prev) {prev.visitCount+=1}";
		Criteria criteria = Criteria.where("access_date").gte(formDate).lt(toDate).and("domain").is(domain);
		int uvcount = detailDao.group(criteria, CollectionNames.COOKIEID, mapFunction, reduceFunction, FlowisStatDetailDTO.class).getKeys();
		return uvcount;
	}

	/**
	 * 定时任务处理IP
	 */
	private int getIpByTime(String formDate, String toDate, String domain) {
		String mapFunction = "{ip: 0}";
		String reduceFunction = "function(doc, prev) {prev.ip+=1}";
		Criteria criteria = Criteria.where("access_date").gte(formDate).lt(toDate).and("domain").is(domain);
		int ipcount = detailDao.group(criteria, CollectionNames.IP, mapFunction, reduceFunction, FlowisStatDetailDTO.class).getKeys();
		return ipcount;
	}

	/**
	 * 定时任务处理newuv
	 */
	private int getNewUVByTime(String formDate, String toDate, String domain) {
		int newuvcount = 0;
		String mapFunction = "{cookieId: 0}";
		String reduceFunction = "function(doc, prev) {prev.cookieId+=1}";
		Criteria criteria = Criteria.where("access_date").gte(formDate).lt(toDate).and("domain").is(domain).and("visitCount").is(1);
		newuvcount = detailDao.group(criteria, CollectionNames.COOKIEID, mapFunction, reduceFunction, FlowisStatDetailDTO.class).getKeys();
		/*for (FlowisStatDetailDTO engine : result) {
			if (engine.getVisitCount().equals(1)) {
				newuvcount = Integer.valueOf(engine.getCookieId().split("\\.")[0]);
			}
		}*/
		return newuvcount;
	}
/**
	 * 按域名统计新访客浏览次数-
	 */
	private Integer countReferDomainByTimeAndDomain(String formDate,
			String toDate,String domain, int type) {
		Query query = null;
		 List<FlowisStatDetailDTO> flow = new ArrayList<FlowisStatDetailDTO>();
		if(type == 1)
		{
			
			query = new Query(Criteria.where("access_date").gte(formDate)
					.lt(toDate).and("visitCount").is(1).and("domain").is(domain));
          
		}
		else
		{
			query = new Query(Criteria.where("access_date").gte(formDate)
					.lt(toDate).and("domain").is(domain));
		}
		flow = mongoTemplate.find(query, FlowisStatDetailDTO.class);
          List<String> listDomainId = new ArrayList<String>();
          for (FlowisStatDetailDTO flowisStatDetailDTO : flow) {
        	  listDomainId.add(flowisStatDetailDTO.getDomainId());
		}
          Query queryCount = new Query(Criteria.where("access_date").gte(formDate)
  				.lt(toDate).and("domainId").in(listDomainId));
		long resultCount = mongoTemplate.count(queryCount, FlowisStatDetailDTO.class);
		return (int)resultCount;
	}
	
}
